<template>
  <div
    class="floating-button"
    :class="{ 'is-dragging': isDragging }"
    :style="{ left: position.x + 'px', top: position.y + 'px' }"
    @mousedown="startDrag"
    @click="handleClick"
  >
    <img v-if="icon" :src="icon" :alt="alt" class="button-icon" />
    <slot v-else />
  </div>
</template>

<script setup lang="ts">
import { reactive, ref, onMounted, onUnmounted } from "vue"

interface Props {
  icon?: string // 图标路径
  alt?: string // 图标 alt 文本
  initialX?: number // 初始 X 位置
  initialY?: number // 初始 Y 位置
  size?: number // 按钮大小
}

const props = withDefaults(defineProps<Props>(), {
  alt: "Floating Button",
  initialX: undefined,
  initialY: undefined,
  size: 70
})

const emit = defineEmits<{
  click: []
}>()

// 悬浮按钮位置
const position = reactive({
  x: props.initialX ?? window.innerWidth - 100,
  y: props.initialY ?? window.innerHeight - 100
})

// 拖拽相关
let isDraggingState = false
let offsetX = 0
let offsetY = 0
const isDragging = ref(false)

// 开始拖拽
function startDrag(e: MouseEvent) {
  offsetX = e.clientX - position.x
  offsetY = e.clientY - position.y
  isDraggingState = false
  isDragging.value = false

  document.addEventListener("mousemove", handleDrag)
  document.addEventListener("mouseup", stopDrag)
}

// 处理拖拽
function handleDrag(e: MouseEvent) {
  isDraggingState = true
  isDragging.value = true

  const newX = e.clientX - offsetX
  const newY = e.clientY - offsetY

  // 限制在窗口范围内
  position.x = Math.max(0, Math.min(newX, window.innerWidth - props.size))
  position.y = Math.max(0, Math.min(newY, window.innerHeight - props.size))
}

// 停止拖拽
function stopDrag() {
  document.removeEventListener("mousemove", handleDrag)
  document.removeEventListener("mouseup", stopDrag)

  setTimeout(() => {
    isDraggingState = false
    isDragging.value = false
  }, 100)
}

// 处理点击
function handleClick(e: MouseEvent) {
  if (!isDraggingState) {
    emit("click")
  }
}

// 监听窗口大小变化
function handleResize() {
  // 确保按钮在可见范围内
  position.x = Math.min(position.x, window.innerWidth - props.size)
  position.y = Math.min(position.y, window.innerHeight - props.size)
}

onMounted(() => {
  window.addEventListener("resize", handleResize)
})

onUnmounted(() => {
  window.removeEventListener("resize", handleResize)
  document.removeEventListener("mousemove", handleDrag)
  document.removeEventListener("mouseup", stopDrag)
})
</script>

<style scoped lang="scss">
.floating-button {
  position: fixed;
  width: v-bind("`${size}px`");
  height: v-bind("`${size}px`");
  cursor: move;
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 9999;

  &:not(.is-dragging) {
    transition: transform 0.3s ease, filter 0.3s ease;
  }

  &:hover:not(.is-dragging) {
    transform: scale(1.1);
    filter: drop-shadow(0 4px 12px rgba(102, 126, 234, 0.5));
  }

  &:active:not(.is-dragging) {
    transform: scale(0.98);
  }

  &.is-dragging {
    transition: none;
    cursor: move;
  }

  .button-icon {
    width: 100%;
    height: 100%;
    pointer-events: none;
    user-select: none;
    object-fit: contain;
    filter: drop-shadow(0 2px 8px rgba(0, 0, 0, 0.15));
  }
}
</style>

